/* 
 * File:   StepCounter.cpp
 * Author: root
 * 
 * Created on October 30, 2015, 1:09 AM
 */

#include "StepCounter.h"

StepCounter* StepCounter::instance = 0;

//StepCounter::StepCounter() {
//}

StepCounter::StepCounter() {
    this->stepCnt = 0;
    this->status = 1;
}

StepCounter::StepCounter(const StepCounter& orig) {
	this->status = orig.status;
	this->stepCnt = orig.stepCnt;
}

StepCounter::~StepCounter() {
}

StepCounter* StepCounter::getInstance()
{
  if ( !StepCounter::instance )
  {
        StepCounter::instance = new StepCounter();
  }
  return StepCounter::instance;
}

int StepCounter::update(const StepData &paraStep)
{
    uint32 tempCnt = 0;
    uint32 tempData = 0;
    uint32 time = paraStep.getTime();
    int result = 0;

    if ( stepBuffer.cnt > 0 )
    {
        if((time <= stepBuffer.back()->getTime()) 
                || (time > (stepBuffer.back()->getTime() + 1800))) 
        {
            stepBuffer.bottom = 0;
            stepBuffer.top = 0;
            stepBuffer.cnt = 0;
            status = 1;
        }
    }
  
    if ( stepBuffer.cnt > 9 )
    {
        stepBuffer.bottom = (stepBuffer.bottom + 1) % 10;
        stepBuffer.cnt--;
    }
  
    stepBuffer.data[stepBuffer.top] = paraStep;
    stepBuffer.cnt++;
    stepBuffer.top = (stepBuffer.top + 1) % 10;

    if(stepBuffer.cnt <= 9)
        return 0;
  

    if ( status == 1 )
    {
        tempCnt = 0;
        tempData = 0;
        while ( tempCnt < stepBuffer.cnt )
        {
            if(!stepBuffer.data[tempCnt++].isValid())
            {
                if(++tempData > 3)
                    return 0;
            }
        }
        if ( countGroup() <= 4 )
        {
            status = 2;
            stepCnt += 10 - tempData;
            return 1;
        }
        return 0;
    }
    if ( status != 2 )
    {
LABEL_21:
        status = 1;
        return 0;
    }
    
    tempCnt = 0;
    tempData = 0;
    while ( tempCnt < stepBuffer.cnt )
    {
        if(stepBuffer.data[tempCnt].isTooWide()) 
            goto LABEL_21;

        if(stepBuffer.data[tempCnt].isTooNarrow())
        {
            if(++tempData > 3)
                goto LABEL_21;
        }
        ++tempCnt;
    }
  
    result = paraStep.isValid();
    if (result)
    {
        stepCnt++;
        return result;
    }
    return result;
}


int StepCounter::countGroup()
{
    return 2;
//  int v1; // r3@1
//  int i; // r6@3
//  int v3; // r0@4
//  StepData *v4; // r0@5
//  StepData *v5; // r7@5
//  int v6; // r0@5
//  int v7; // r4@5
//  int v8; // r5@5
//  int v9; // r1@5
//  int v10; // r0@5
//  int v11; // r1@5
//  int v12; // r0@5
//  int v13; // r1@5
//  int v14; // r0@6
//  int v15; // r1@6
//  int v16; // r4@6
//  int v17; // r1@6
//  int v18; // r5@6
//  int v19; // r3@6
//  int v20; // r2@6
//  int v21; // r0@6
//  int v22; // r1@6
//  int v23; // r1@6
//  StepData *v24; // r5@8
//  int v25; // r0@8
//  int v26; // r2@8
//  int v27; // r6@8
//  int v28; // r1@8
//  int v29; // r3@12
//  int v30; // r2@12
//  unsigned int *v31; // r1@14
//  int v32; // r7@17
//  int v33; // r0@18
//  int v34; // r2@18
//  int v35; // r3@18
//  int v36; // r6@18
//  StepGroup *j; // r6@19
//  int v38; // r4@26
//  int v39; // r6@26
//  StepGroup *v40; // r5@27
//  unsigned int v42; // [sp+Ch] [bp-64h]@14
//  unsigned int *v43; // [sp+Ch] [bp-64h]@26
//  int v44; // [sp+10h] [bp-60h]@2
//  StepCounter *v45; // [sp+14h] [bp-5Ch]@1
//  int v46; // [sp+18h] [bp-58h]@19
//  int v47; // [sp+1Ch] [bp-54h]@19
//  char v48; // [sp+24h] [bp-4Ch]@18
//  unsigned int v49; // [sp+28h] [bp-48h]@17
//  int v50; // [sp+2Ch] [bp-44h]@1
//  int v51; // [sp+30h] [bp-40h]@1
//  int v52; // [sp+34h] [bp-3Ch]@1
//  int v53; // [sp+38h] [bp-38h]@8
//  int v54; // [sp+3Ch] [bp-34h]@8
//  int v55; // [sp+40h] [bp-30h]@8
//  int v56; // [sp+48h] [bp-28h]@8
//  int v57; // [sp+4Ch] [bp-24h]@8
//  int v58; // [sp+50h] [bp-20h]@8
//  int v59; // [sp+54h] [bp-1Ch]@8
//
//  v1 = 0;
//  v45 = this;
//  v50 = 0;
//  v51 = 0;
//  v52 = 0;
//  while ( 1 )
//  {
//    v44 = v1;
//    if ( v1 >= *((_DWORD *)v45 + 126) )
//      break;
//    for ( i = v50; ; i += 32 )
//    {
//      v3 = (int)((char *)v45 + 16);
//      if ( i == v51 )
//        break;
//      v4 = (StepData *)Buffer<StepData,10>::operator[](v3, v44);
//      v5 = v4;
//      v6 = StepData::getLevel(v4);
//      v7 = *(_DWORD *)(i + 16);
//      v8 = *(_DWORD *)(i + 20);
//      v10 = j_j___subdf3(v6, v9, *(_DWORD *)(i + 16), *(_DWORD *)(i + 20));
//      v12 = j_j___divdf3(v10, (unsigned int)(2 * v11) >> 1, v7, v8);
//      if ( j_j___aeabi_dcmplt(v12, v13, -1717986918, 1070176665) ) // 0.2
//      {
//        std::vector<StepData,std::allocator<StepData>>::push_back(i, v5);
//        v14 = StepData::getLevel(v5);
//        v16 = j_j___aeabi_dadd(v14, v15, *(_DWORD *)(i + 24), *(_DWORD *)(i + 28));
//        v18 = v17;
//        v19 = *(_DWORD *)(i + 4);
//        v20 = *(_DWORD *)i;
//        *(_DWORD *)(i + 24) = v16;
//        *(_DWORD *)(i + 28) = v17;
//        v21 = j_j___floatunsidf(-1431655765 * ((v19 - v20) >> 4));
//        *(_DWORD *)(i + 16) = j_j___divdf3(v16, v18, v21, v22);
//        *(_DWORD *)(i + 20) = v23;
//        goto LABEL_25;
//      }
//    }
//    
//    // since it is super confusing, just try to figure out one by one.
//    // vectorBuffer.push_back(this->stepBuffer[v44]);
//    // v25 = this->stepBuffer[v44].getLevel();
//    
//    v24 = (StepData *)Buffer<StepData,10>::operator[](v3, v44);
//    v54 = 0;
//    v55 = 0;
//    v53 = 0;
//    std::vector<StepData,std::allocator<StepData>>::push_back(&v53, v24);
//    v25 = StepData::getLevel(v24);
//    v27 = v51;
//    v56 = v25;
//    v57 = v28;
//    v58 = v25;
//    v59 = v28;
//    if ( v51 == v52 )
//    {
//      v29 = (v51 - v50) >> 5;
//      v30 = (v51 - v50) >> 5;
//      if ( !v29 )
//        v30 = 1;
//      v42 = v30 + v29;//first time v42  is 1;
//      v31 = (unsigned int *)(v30 + v29);// first time v31 is 1;
//      if ( (unsigned int)(v30 + v29) > 0x7FFFFFF || (unsigned int)v31 < v29 )
//      {
//        v42 = 0x7FFFFFF;
//        goto LABEL_17;
//      }
//      v32 = v30 + v29;// first cycle it is 1;
//      if ( v42 )
//      {
//LABEL_17:
//        v49 = 32 * v42;
//        v32 = std::__node_alloc::allocate((std::__node_alloc *)&v49, v31); //  allocate v31 ge 32 * v42;
//        v42 = v49 >> 5; // v42 is how many we got.
//      }
//      //copy some data to the new memory which pointed by v32.
//      v33 = std::priv::__ucopy<StepGroup *,StepGroup *,int>(v50, v27, v32, (int)&v48);
//      // v36 equal the end address
//      v36 = v33;
//      // copy v53 to v33 
//      if ( v33 )
//        StepGroup::StepGroup(v33, (int)&v53, v34, v35);
//      // first cycle v46 = v33 address move forward 32 bytes.
//      v46 = v36 + 32;
//      v47 = v50;
//      for ( j = (StepGroup *)v51; j != (StepGroup *)v47; StepGroup::~StepGroup(j) )
//        j = (StepGroup *)((char *)j - 32);
//      // delete v50;
//      sub_55B6(v50);
//      // v32 is the pointer to the new memory
//      // v52 is the last one.
//      v50 = v32;
//      v51 = v46;
//      v52 = v32 + 32 * v42;
//      goto LABEL_24;
//    }
//    if ( v51 )
//      StepGroup::StepGroup(v51, (int)&v53, v26, v52);
//    v51 += 32;
//LABEL_24:
//    // delete the temp stepdata object
//    StepGroup::~StepGroup((StepGroup *)&v53);
//LABEL_25:
//    v1 = v44 + 1;
//  }
//  v38 = v50;
//  v43 = (unsigned int *)v51;
//  v39 = (v51 - v50) >> 5;
//  // if get some copy
//  if ( v50 != v51 )
//  {
//      // deconstructor all here;
//    v40 = (StepGroup *)v50;
//    do
//    {
//      StepGroup::~StepGroup(v40);
//      v40 = (StepGroup *)((char *)v40 + 32);
//    }
//    while ( (unsigned int *)v40 != v43 );
//    v51 = v38;
//  }
//  std::vector<StepGroup,std::allocator<StepGroup>>::~vector((int)&v50);
//  // return how many stepgroup we have.
//  return v39;
}


//int StepCounter::set(uint32 a2)
//{
//    this->status = 1;
//    this->stepBuffer.bottom = 0;
//    this->stepBuffer.top = 0;
//    this->stepBuffer.cnt = a2;
//}

void StepCounter::set(uint32 a2)
{
    this->status = 1;
    this->stepBuffer.bottom = 0;
    this->stepBuffer.top = 0;
    this->stepBuffer.cnt = 0;
    this->stepCnt = a2;
}

void StepCounter::reset()
{
    this->status = 1;
    this->stepBuffer.bottom = 0;
    this->stepBuffer.top = 0;
    this->stepBuffer.cnt = 0;
	this->stepCnt = 0;
}

void StepCounter::release()
{
    if ( this->getInstance() )
    {
        delete this->getInstance();
    }
}

int StepCounter::get()
{
    return this->stepCnt;
}

